package crypto

import (
	"fmt"
	"math/big"
)

// Secp256k1Adapter adapts secp256k1 to the existing BLS interface
type Secp256k1Adapter struct {
	threshold *Secp256k1Threshold
}

// NewSecp256k1Adapter creates a new adapter
func NewSecp256k1Adapter() *Secp256k1Adapter {
	return &Secp256k1Adapter{
		threshold: NewSecp256k1Threshold(),
	}
}

// Adapter types that map to existing interfaces
type AdapterG1 struct{ *Secp256k1Point }
type AdapterG2 struct{ *Secp256k1Signature }
type AdapterZR struct{ *Secp256k1Scalar }
type AdapterGT struct{ *Secp256k1Signature }

// Convert secp256k1 types to adapter types
func (a *Secp256k1Adapter) ToG1(point *Secp256k1Point) *AdapterG1 {
	return &AdapterG1{point}
}

func (a *Secp256k1Adapter) ToG2(sig *Secp256k1Signature) *AdapterG2 {
	return &AdapterG2{sig}
}

func (a *Secp256k1Adapter) ToZR(scalar *Secp256k1Scalar) *AdapterZR {
	return &AdapterZR{scalar}
}

func (a *Secp256k1Adapter) ToGT(sig *Secp256k1Signature) *AdapterGT {
	return &AdapterGT{sig}
}

// Convert adapter types back to secp256k1 types
func (g *AdapterG1) ToSecp256k1() *Secp256k1Point {
	return g.Secp256k1Point
}

func (g *AdapterG2) ToSecp256k1() *Secp256k1Signature {
	return g.Secp256k1Signature
}

func (z *AdapterZR) ToSecp256k1() *Secp256k1Scalar {
	return z.Secp256k1Scalar
}

func (g *AdapterGT) ToSecp256k1() *Secp256k1Signature {
	return g.Secp256k1Signature
}

// Implement the BLS interface using secp256k1

// HashMessage hashes a message to a G2 element (signature)
func (a *Secp256k1Adapter) HashMessage(message interface{}) *AdapterG2 {
	// For secp256k1, we hash to a scalar and create a signature
	scalar := a.threshold.HashMessage(message)
	// Create a dummy signature for the hash
	sig := &Secp256k1Signature{
		R: scalar.Int,
		S: big.NewInt(0),
	}
	return a.ToG2(sig)
}

// Sign signs a message with a private key
func (a *Secp256k1Adapter) Sign(sk *AdapterZR, message interface{}) *AdapterG2 {
	var data []byte
	switch m := message.(type) {
	case []byte:
		data = m
	case string:
		data = []byte(m)
	default:
		data = []byte(fmt.Sprintf("%v", m))
	}
	
	sig := sk.ToSecp256k1().Sign(data)
	return a.ToG2(sig)
}

// VerifyShare verifies a signature share
func (a *Secp256k1Adapter) VerifyShare(pk *AdapterG1, sig *AdapterG2, message interface{}) bool {
	var data []byte
	switch m := message.(type) {
	case []byte:
		data = m
	case string:
		data = []byte(m)
	default:
		data = []byte(fmt.Sprintf("%v", m))
	}
	
	return a.threshold.VerifyShare(pk.ToSecp256k1(), sig.ToSecp256k1(), data)
}

// CombineShares combines signature shares using Lagrange interpolation
func (a *Secp256k1Adapter) CombineShares(sigs map[int]*AdapterG2, indices []int) *AdapterG2 {
	sigMap := make(map[int]*Secp256k1Signature)
	for k, v := range sigs {
		sigMap[k] = v.ToSecp256k1()
	}
	
	combined := a.threshold.CombineShares(sigMap, indices)
	return a.ToG2(combined)
}

// VerifySignature verifies a complete signature
func (a *Secp256k1Adapter) VerifySignature(pk *AdapterG1, sig *AdapterG2, message interface{}) bool {
	var data []byte
	switch m := message.(type) {
	case []byte:
		data = m
	case string:
		data = []byte(m)
	default:
		data = []byte(fmt.Sprintf("%v", m))
	}
	
	return a.threshold.VerifyThresholdSignature(pk.ToSecp256k1(), sig.ToSecp256k1(), data)
}

// GenerateThresholdKeys generates threshold signature keys
func (a *Secp256k1Adapter) GenerateThresholdKeys(n, t int) (*AdapterG1, []AdapterG1, []AdapterZR) {
	keySet := a.threshold.GenerateThresholdKeys(n, t)
	
	// Convert threshold public key
	thresholdPK := a.ToG1(keySet.ThresholdPK)
	
	// Convert public keys
	pks := make([]AdapterG1, n)
	for i, share := range keySet.Shares {
		pks[i] = *a.ToG1(share.PubKey)
	}
	
	// Convert private key shares
	sks := make([]AdapterZR, n)
	for i, share := range keySet.Shares {
		sks[i] = *a.ToZR(share.Share)
	}
	
	return thresholdPK, pks, sks
}

// ThresholdSign signs a message with threshold signature
func (a *Secp256k1Adapter) ThresholdSign(sks []AdapterZR, message interface{}, signers []int) *AdapterG2 {
	if len(sks) != len(signers) {
		panic("number of private keys must match number of signers")
	}
	
	// Generate signature shares
	sigShares := make(map[int]*Secp256k1Signature)
	for i, sk := range sks {
		var data []byte
		switch m := message.(type) {
		case []byte:
			data = m
		case string:
			data = []byte(m)
		default:
			data = []byte(fmt.Sprintf("%v", m))
		}
		
		sig := a.threshold.SignShare(sk.ToSecp256k1(), data)
		sigShares[signers[i]] = sig
	}
	
	// Combine shares
	combined := a.threshold.CombineShares(sigShares, signers)
	return a.ToG2(combined)
}

// ThresholdVerify verifies a threshold signature
func (a *Secp256k1Adapter) ThresholdVerify(thresholdPK *AdapterG1, sig *AdapterG2, message interface{}) bool {
	return a.VerifySignature(thresholdPK, sig, message)
}

// Helper functions for compatibility

// lagrangeCoefficient computes Lagrange coefficient for interpolation
func (a *Secp256k1Adapter) lagrangeCoefficient(indices []int, j int) *AdapterZR {
	coeff := a.threshold.lagrangeCoefficient(indices, j)
	return a.ToZR(coeff)
}

// evalPolynomial evaluates a polynomial at a given point
func (a *Secp256k1Adapter) evalPolynomial(coeffs []AdapterZR, x int64) *AdapterZR {
	secpCoeffs := make([]*Secp256k1Scalar, len(coeffs))
	for i, coeff := range coeffs {
		secpCoeffs[i] = coeff.ToSecp256k1()
	}
	
	result := a.threshold.evalPolynomial(secpCoeffs, big.NewInt(x))
	return a.ToZR(result)
}

// Global secp256k1 adapter instance (lazy initialization)
var defaultSecp256k1Adapter *Secp256k1Adapter

// GetDefaultSecp256k1Adapter returns the default adapter instance
func GetDefaultSecp256k1Adapter() *Secp256k1Adapter {
	if defaultSecp256k1Adapter == nil {
		defaultSecp256k1Adapter = NewSecp256k1Adapter()
	}
	return defaultSecp256k1Adapter
}

// Convenience functions using the global adapter instance

// HashMessage hashes a message using the default adapter
func HashMessageSecp256k1(message interface{}) *AdapterG2 {
	return GetDefaultSecp256k1Adapter().HashMessage(message)
}

// Sign signs a message using the default adapter
func SignSecp256k1(sk *AdapterZR, message interface{}) *AdapterG2 {
	return GetDefaultSecp256k1Adapter().Sign(sk, message)
}

// VerifyShare verifies a signature share using the default adapter
func VerifyShareSecp256k1(pk *AdapterG1, sig *AdapterG2, message interface{}) bool {
	return GetDefaultSecp256k1Adapter().VerifyShare(pk, sig, message)
}

// CombineShares combines signature shares using the default adapter
func CombineSharesSecp256k1(sigs map[int]*AdapterG2, indices []int) *AdapterG2 {
	return GetDefaultSecp256k1Adapter().CombineShares(sigs, indices)
}

// VerifySignature verifies a signature using the default adapter
func VerifySignatureSecp256k1(pk *AdapterG1, sig *AdapterG2, message interface{}) bool {
	return GetDefaultSecp256k1Adapter().VerifySignature(pk, sig, message)
}

// GenerateThresholdKeys generates threshold keys using the default adapter
func GenerateThresholdKeysSecp256k1(n, t int) (*AdapterG1, []AdapterG1, []AdapterZR) {
	return GetDefaultSecp256k1Adapter().GenerateThresholdKeys(n, t)
}

// ThresholdSign signs with threshold signature using the default adapter
func ThresholdSignSecp256k1(sks []AdapterZR, message interface{}, signers []int) *AdapterG2 {
	return GetDefaultSecp256k1Adapter().ThresholdSign(sks, message, signers)
}

// ThresholdVerify verifies threshold signature using the default adapter
func ThresholdVerifySecp256k1(thresholdPK *AdapterG1, sig *AdapterG2, message interface{}) bool {
	return GetDefaultSecp256k1Adapter().ThresholdVerify(thresholdPK, sig, message)
}
